<template>
<div id="app">
    <div class="box" v-if="able">
        <h1> online chatroom </h1>
        <div class="status">
            <div>
                <el-button
                :disabled="connected"
                    type="primary"
                    style="width:20%;height: 25px;margin-bottom:30px;"
                    @click.native.prevent="connect"
                >登录</el-button>
                <el-button
                :disabled="!connected"
                    type="primary"
                    style="width:20%;height: 25px;margin-bottom:30px;"
                    @click.native.prevent="disconnect"
                >退出</el-button>
            </div>
            您的状态：<em :style="'color:' + (connected ? 'green':'red') ">
            {{ connected ? '登录':'退出' }}
        </em>
        </div>

        <div>
            <h2>在线用户列表</h2>
            <button @click="getUsers">刷新用户</button>
            <ul>
                <li v-for="(u,index) in online_users"
                    :key="index"
                    @click="talk_to = u.userId">
                    <a href="javascript:;">{{u.userId}} - {{u.userName}}</a>
                </li>
            </ul>
        </div>

        <div class="talk-panel">
            <h2>发送消息</h2>
            发送对象: <input v-model.trim="talk_to"><br/>
            <button @click="sendMessageWX">发送消息给微信公众号</button>
        </div>

        <div class="chat_box">
            <header>聊天消息</header>
            <div class="msg_box" ref="msg_box">
                <div v-for="(item,index) in talk_history" :key="index" class="msg"
                     :style="item.from == userId? 'flex-direction:row-reverse' : ''">
                    <div class="user-head" v-if="userId">
                        <div class="head">{{item.from}}</div>
                    </div>
                    <div class="user_msg" v-if="userId">
                      <span :style="item.from == userId ? 'float: right;' : ''" :class="item.from == userId ? 'right' : 'left'">
                        {{item.message}}
                      </span>
                    </div>
                </div>
            </div>
            <div class="input_box">
                <span class="info">消息:</span>
                <input type="text" v-model="talk_content" @keyup.enter="sendMessage()"/>
                <div class="btn" @click="sendMessage()">发送</div>
            </div>
        </div>

    </div>
</div>
</template>

<script>
export default {
  name: 'imdemo',
  data () { // 数据
    return {
      ACTION_999: '999',
      manualStop: true,
      APP_VERSION: "1.0.0",
      APP_CHANNEL: "web",
      PONG: 0,
      PING: 1,
      MESSAGE: 2,
      SENT_BODY: 3,
      REPLY_BODY: 4,
      PONG_BODY: "PONG",
      userId: '',
      passwd: '',
      online_users: [],
      able: true, // 浏览器是否支持 ws
      timer:null, //定时器名称
      talk_to: undefined,
      talk_content: undefined, // 聊天内容
      connected: false,//是否已连接
      ws_url: "ws://im.mianduijifeng.top:34569/im",   // ws暴露地址
      socket: undefined,
      talk_history: []
    }
  },
  created () { // 挂载
    if (typeof (WebSocket) === 'undefined') {
        this.message('您的浏览器不支持 websocket !')
        this.able = false
    }
    this.getlist()
  },
  methods: { // 方法
    getlist () {
      console.log('getlist')
    },
    onInterceptMessageReceived(message) {
        console.log("onInterceptMessageReceived:",message)
        /*
            *被强制下线之后，不再继续连接服务端
            */
        if (message.action === this.ACTION_999) {
            this.manualStop = true;
        }
        /*
            *收到消息后，将消息发送给页面
            */
        this.talk_history.push({time: this.thisTime(), from: message.sender, to: 'Me', message: message.content})
    },
    getUsers(){
      this.req({
        url: "user/list",
        method: "GET"
      }).then(
        res => {
          console.log("res :", res.data);
          this.online_users = res.data
        },
        err => {
          console.error("err :", err);
          this.passwordError = true;
          this.loading = false;
        }
      );
    },
    sendMessageJson(toUrl, params = {}) {
        this.req({
            url: toUrl,
            data: params,
            method: "POST"
        }).then(
            res => {
                console.log("sendMessageJson res :", res.data);
            },
            err => {
                console.error("err :", err);
            }
        );
    },
    getBrowser() {
        let explorer = window.navigator.userAgent.toLowerCase();
        if (explorer.indexOf("msie") >= 0) {
            let ver = explorer.match(/msie ([\d.]+)/)[1];
            return {name: "IE", version: ver};
        }
        else if (explorer.indexOf("firefox") >= 0) {
            let ver = explorer.match(/firefox\/([\d.]+)/)[1];
            return {name: "Firefox", version: ver};
        }
        else if (explorer.indexOf("chrome") >= 0) {
            let ver = explorer.match(/chrome\/([\d.]+)/)[1];
            return {name: "Chrome", version: ver};
        }
        else if (explorer.indexOf("opera") >= 0) {
            let ver = explorer.match(/opera.([\d.]+)/)[1];
            return {name: "Opera", version: ver};
        }
        else if (explorer.indexOf("Safari") >= 0) {
            let ver = explorer.match(/version\/([\d.]+)/)[1];
            return {name: "Safari", version: ver};
        }

        return {name: "Other", version: "1.0.0"};
    },
    generateUUID() {
        let d = new Date().getTime();
        let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            let r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
        return uuid.replace(/-/g, '');
    },
    sendRequest(body){
        let data = {};
        data.type = this.SENT_BODY;
        data.content = JSON.stringify(body);
        this.socket.send(JSON.stringify(data));
    },
    pong () {
        let data = {};
        data.type = this.PONG;
        data.content = this.PONG_BODY;
        this.socket.send(JSON.stringify(data));
    },
    bind(){
        console.log("绑定连接")

        let deviceId = window.localStorage.deviceId;
        if (deviceId === '' || deviceId === undefined) {
            deviceId = this.generateUUID();
            window.localStorage.deviceId = deviceId;
        }

        let body = {};
        body.key ="client_bind";
        body.timestamp=new Date().getTime();
        body.data = {};
        body.data.uid = this.userId;
        body.data.deviceId = deviceId;
        body.data.deviceName = this.getBrowser().name;

        // let body = {from: this.userId, to: this.talk_to, text: this.talk_content, key: "client_bind"}

        body.data.channel = this.APP_CHANNEL;
        body.data.appVersion = this.APP_VERSION;

        this.sendRequest(body);

        setTimeout(this.getUsers, 1000)
    },
    connect() {
        this.userId = localStorage.getItem("userId");
        if (this.connected) {
            alert('已连接')
            return
        }
        // 如果开启则关闭
        if (this.socket) {
            this.socket.close()
            this.socket = null
        }

        let token = localStorage.getItem("token");

        console.log("token ", token)

        if (!token || token === '') {
            alert('获取token失败')
            return
        }
        // 初始化
        this.talk_to = undefined
        this.talk_content = undefined
        this.talk_history = []
        this.online_users = []
        // 建立连接，编写回调localhost:34569/im/
        let ws_url_token = this.ws_url + '?token='+token
        let that = this
        this.socket = new WebSocket(ws_url_token)
        this.socket.binaryType = "arraybuffer";
        this.socket.onopen = function () {
            console.log("建立连接")
            console.log(ws_url_token)
            that.connected = true
            that.bind();
            that.manualStop = false;
        }
        this.socket.onmessage = function (msg) {
            console.log('收到消息:')
            let data = JSON.parse(msg.data)
            let type = data.type;
            let body = data.content;

            console.log(data)

            if (type === that.PING) {
                console.log("PING")
                that.pong();
                return;
            }

            if (type === that.MESSAGE) {
                console.log("MESSAGE:",body)
                let message = JSON.parse(body);
                that.onInterceptMessageReceived(message);
                return;
            }

            if (type === that.REPLY_BODY) {
                console.log("REPLY_BODY");
                let reply = JSON.parse(body);
                console.log(reply);
                if(reply.key==='client_bind' && reply.code === "200" ){
                    console.log("reply success");
                }
                return;
            }

            alert("OTHER")
        }
        this.socket.onerror = function () {
            console.log('onerror, ws 发生了错误')
        }
        this.socket.onclose = function () {
            console.log('连接已关闭')
            if (!that.manualStop) {
                console.log('重连')
                let time = Math.floor(Math.random() * (30 - 15 + 1) + 15);
                setTimeout(function () {
                    that.connect();
                }, time);
            }
            that.connected = false
            that.online_users = []
            that.talk_history = []
            that.talk_to = undefined
            that.talk_content = undefined
        }
    },
    disconnect() {
        console.log('disconnect')
        this.manualStop = true
        if (!this.connected) {
            alert('已关闭')
        }
        if (this.socket) {
            this.socket.close()
        }
        this.socket = null
    },
    thisTime() {
        const now = new Date()
        return now.getDate() + "/" + (now.getMonth() + 1) + "/" + now.getFullYear() + " " +
            now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds()
    },
    sendMessageWX() {
        if (!this.connected || !this.socket) {
            alert('请先登录')
            return
        }
        this.talk_to = 'o9bmJ6KO5gHAYQX7qCNsV8girzs4'

        if (!this.talk_content || this.talk_content === '') {
            alert('请输入聊天内容')
            return
        }
        console.log('talk_to userId = ', this.talk_to, ', msg = ', this.talk_content)

        let msg = {content:this.talk_content,action:'3',sender:this.userId,receiver:this.talk_to,format:'0'}

        this.sendMessageJson("message/sendJson",msg);

        this.talk_history.push({time: this.thisTime(), from: this.userId, to: this.talk_to, message: this.talk_content})
    },
    sendMessage() {
        console.log("sendMessage")
        if (!this.connected || !this.socket) {
            alert('请先登录')
            return
        }
        if (!this.talk_to) {
            alert('请选择聊天对象')
            return
        }
        if (!this.talk_content || this.talk_content === '') {
            alert('请输入聊天内容')
            return
        }
        console.log('talk_to userId = ', this.talk_to, ', msg = ', this.talk_content)

        let msg = {content: this.talk_content,action:2,sender:this.userId,receiver:this.talk_to,format:'0'}

        this.sendMessageJson("message/sendJson",msg,true);

        this.talk_history.push({time: this.thisTime(), from: this.userId, to: this.talk_to, message: this.talk_content})
    },
  },
  computed: {
  }
}
</script>

<style scoped>
    * {
        margin: 0;
        padding: 0;
    }

    .box {
        width: 50%;
        margin: 20px auto 0;
    }

    .box > div {
        margin-top: 20px;
    }

    .box > div:nth-child(odd) {
        background-color: #fafafa;
    }

    .box .talk-panel p:nth-child(odd) {
        background-color: #f5f5f5;
    }
    .chat_box {
        margin: 0 auto;
        background: #6fc6e1;
        position: absolute;
        height: 500px;
        width: 50%;
    }

    .chat_box header{
        position: absolute;
        width: 100%;
        height: 3rem;
        background: #409eff;
        display: flex;
        justify-content: center;
        align-items: center;
        font-weight: bold;
        color: white;
        font-size: 1rem;
        z-index: 999;
    }

    .chat_box .msg_box{
        position: absolute;
        height: 100%;
        width: 100%;
        overflow-y: auto;
        box-sizing: border-box;
        padding: 3rem 0;
        background: #cee2e8;
    }
    .chat_box .msg_box .msg{
        width: 95%;
        min-height: 2.5rem;
        margin: 1rem 0.5rem;
        position: relative;
        display: flex;
        justify-content: flex-start !important;
    }
    .chat_box .msg_box .msg .user-head{
        min-width: 2.5rem;
        width: 20%;
        width: 2.5rem;
        height: 2.5rem;
        border-radius: 50%;
        background: #f1f1f1;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .chat_box .msg_box .msg .user-head .head{
        width: 1.2rem;
        height: 1.2rem;
    }

    .chat_box .msg_box .msg .user_msg{
        width: 80%;
        word-break: break-all;
        position: relative;
        z-index: 5;
    }
    .chat_box .msg_box .msg .user_msg span{
        display: inline-block;
        padding: 0.5rem 0.7rem;
        border-radius: 0.5rem;
        margin-top: 0.2rem;
        font-size: 0.88rem;
    }
    .chat_box .msg_box .msg .user_msg .left{
        background: white;
        animation: toLeft 0.5s ease both 1;
    }
    .chat_box .msg_box .msg .user_msg .right{
        background: #7dc6dc;
        color: white;
        animation: toright 0.5s ease both 1;
    }
    @keyframes toLeft {
        0% {
            opacity: 0;
            transform: translateX(-10px);
        }
        100% {
            opacity: 1;
            transform: translateX(0px);
        }
    }
    @keyframes toright {
        0% {
            opacity: 0;
            transform: translateX(10px);
        }
        100% {
            opacity: 1;
            transform: translateX(0px);
        }
    }

    .chat_box .input_box{
        position: absolute;
        bottom: 0;
        width: 100%;
        height: 2.5rem;
        background: #fafafa;
        box-shadow: 0 0 5px #ccc;
        display: flex;
        justify-content: space-between;
        align-items: center;
        z-index: 999;
    }

    .chat_box .input_box input{
        height: 2.3rem;
        display: inline-block;
        width: 100%;
        border: none;
        border-radius: 0.2rem;
        font-size: 0.88rem;
    }
    .chat_box .input_box .info{
        min-width: 4rem;
        font-size: 1.1rem;
        text-align: center;
        border-radius: 0.2rem;
        margin-left: 0.5rem;
        transition: 0.5s;
        background: #3b8fa9;
    }
    .chat_box .input_box .btn{
        min-width: 4rem;
        background: #409eff;
        font-size: 1.1rem;
        color: white;
        text-align: center;
        border-radius: 0.2rem;
        margin-left: 0.5rem;
        transition: 0.5s;
    }
</style>
